﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Diggins.Jigsaw;
using Domains;

namespace Parser
{
    public class Evaluator4
    {
        public StringBuilder builder = new StringBuilder();
        public StringBuilder blockBuilder = new StringBuilder();
        public string Evaluate(Node n)
        {
            builder.Clear();
            blockBuilder.Clear();
            switch (n.Label)
            {
                case "Program":
                    {
                        builder.Append(Evaluate(n[0]));
                        for (int i = 1; i < n.Count; i++)
                        {
                            builder.Append("*");
                            builder.Append(Evaluate(n[i]));
                        }
                        return builder.ToString();
                    }
                case "VarDecl":
                    {
                        return String.Format("{0} * (^ v => ^ m => ^ i => ^ o => ( m[ {1} / v ] ! i ! o ))", (Evaluate(n[1])), n[0].Text);
                    }
                case "output":
                    {
                        return String.Format("{0} * (^ v => ^ m => ^ i => ^ o => (m ! i ! v & o))", Evaluate(n[0]));
                    }
                case "If":
                    {
                        return String.Format("{0} * ckeckBool * (^ v => ^ m => ^ i => ^ o => v = true then {1} else {0})",
                                Evaluate(n[0]), Evaluate(n[1]), Evaluate(n[2]));
                    }
                case "Else":
                    {
                        return Evaluate(n[0]);
                    }
                case "Block":
                    {

                        blockBuilder.Append(Evaluate(n[0]));
                        for (int i = 1; i < n.Count; i++)
                        {
                            blockBuilder.Append("*");
                            blockBuilder.Append(Evaluate(n[i]));
                        }
                        var result = blockBuilder.ToString();
                        blockBuilder.Clear();
                        return builder.ToString();
                    }
                case "Expr":
                    {
                        switch (n[0].Label)
                        {
                            case "read":
                                {
                                    return "^ m => ^ i => ^ o => empty i then error else ( head i ! ( m ! tail i ! o ))";
                                }
                            case "False":
                                return "false";
                            case "True":
                                return "true";
                            case "Integer":
                                return n.Text;
                            case "BinaryExpr":
                                {
                                    switch (n[0][1].Text)
                                    {
                                        case "+":
                                            {
                                                return String.Format("{0} * isNum * ^ v1 => {1} * isNum * ^ v2 => ( v1 + v2 ! ( m ! i ! o ))", 
                                                    Evaluate(n[0][0]), Evaluate(n[0][2]));
                                            }
                                        case "=":
                                            {
                                                return String.Format("{0} * ^ v1 => {1}  * ^ v2 => ( v1 = v2 ! ( m ! i ! o ))", 
                                                    Evaluate(n[0][0]), Evaluate(n[0][2]));
                                            }
                                        default: throw new Exception("unsupported binary operation");
                                    }
                                }
                            case "PrefixExpr":
                                {
                                    switch (n[0][0].Text)
                                    {
                                        case "not":
                                            {
                                                var uselessNode = n[0][1];
                                                var eval = Evaluate(uselessNode[0]);

                                                return String.Format("{0} * isBool * ^ v => (not v ! ( m ! i ! o ))", eval);
                                            }
                                        default : throw new Exception("unsupported unary operation");
                                    }
                                }
                            case "Identifier":
                                {
                                    return n.Text; 
                                }
                        }
                        break;
                    }
                case "Identifier":
                    {
                        return n.Text;                       
                    }
                case "False":
                    return "false";
                case "True":
                    return "true";
                case "Integer":
                    return n.Text;
                default: throw new Exception("unsupported comman or exprecion");
            }
            return "error";
        }
    
    }
}

